package csci6450.chickenFriedFS.nuggetShell;

import csci6450.chickenFriedFS.nuggetClient.NuggetClient;
import csci6450.chickenFriedFS.nuggetClient.RuntimeSettings;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

public class NuggetShell {

    public NuggetShell() {
    }

    //Local
    public ArrayList<String> localGetFileNameList() {
        File file = new File(".");
        String[] fileList = file.list();
        Arrays.sort(fileList);
        System.out.println("Local Directory Listing:");
        System.out.println("");
        for (int i = 0; i < fileList.length; i = i + 1) {
            System.out.println(file.getAbsolutePath().replaceAll("\\.", "") + fileList[i]);
        }
        return null;
    }

    public File localGetFile(String fileName) {
        return null;
    }

    public boolean localAddFile(File file) {
        if (file.exists()) {
            return true;
        } else {
            System.out.println("Can't find file " + file.getAbsolutePath() + ".");
            return false;
        }
    }

    public boolean localRemoveFile(String fileName) {
        return false;
    }

    public boolean localFormat() {
        return false;
    }

    public long localGetAvailableDiskSpace() {
        if (System.getProperty("os.name").contains("Windows")) {
        }
        return 7;
    }
    //End Local

    //Remote
    public ArrayList<String> getFileNameList() throws UnknownHostException, IOException, ClassNotFoundException {
        return NuggetClient.getFileNameList();
    }

    public boolean getFile(String fileName, String saveTo) {
        boolean success = false;
        try {
            success = NuggetClient.getFile(fileName, saveTo);
            File g = new File(fileName);
            System.out.println("Last chance := "+g.length());
        } catch (UnknownHostException ex) {
            System.out.println("Unable to connect to remote server.");
            Logger.getLogger(NuggetShell.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            System.out.println("Sorry there were network problems.");
            Logger.getLogger(NuggetShell.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            System.out.println("If you get this message, come find me and punch me in the face.");
            Logger.getLogger(NuggetShell.class.getName()).log(Level.SEVERE, null, ex);
        }
        return success;
    }

    public boolean addFile(File file) throws UnknownHostException, IOException, ClassNotFoundException {
        if (file.exists()) {
            boolean success = NuggetClient.addFile(file);
            if (!success) {
                System.out.println("Your chicken was cut in to pieces, but was somehow misplaced suring shipping.");
            }
            return success;
        } else {
            System.out.println("Can't find file " + file.getAbsolutePath() + ".");
            return false;
        }
    }

    public boolean removeFile(String fileName) throws UnknownHostException, IOException, ClassNotFoundException {
        boolean success = NuggetClient.removeFile(fileName);
        System.out.println((success ? "File successfully Removed." : "Sorry there was a problem and the Chicken got loose."));
        return success;
    }

    public boolean format() throws IOException, ClassNotFoundException {
        return NuggetClient.format();
    }

    public void getAvailableDiskSpace() {
        try {
            long free = NuggetClient.getFreeSpace();
            System.out.println("Disk Free Space := " + free + " bytes");
        } catch (IOException iOException) {
            System.out.println("Sorry the Chicken escaped!");
            iOException.printStackTrace();
        } catch (ClassNotFoundException classNotFoundException) {
            System.out.println("Sorry the Chicken escaped!");
            classNotFoundException.printStackTrace();
        }
    }
    //End Remote

    public byte[] convertFileToBytes(File file) {
        byte[] fileBytes = new byte[(int) file.length()];
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(fileBytes);
            return fileBytes;
        } catch (FileNotFoundException e) {
            System.out.println("Can't find file " + file.getAbsolutePath() + ".");
        } catch (IOException e1) {
            System.out.println("Can't read file. " + file.getAbsolutePath() + ".");
        }
        return null;
    }

    public void displayFormatMessage(String fromUser) {
        System.out.println("Format ERROR");
        System.out.println("You typed: " + fromUser + "");
        System.out.println("You should have typed 'PUT', 'GET', 'LS'");
    }

    public void run() throws IOException, UnknownHostException, ClassNotFoundException {
        System.out.println("NuggetShell.start()");
        System.out.println("Your parent OS is " + System.getProperty("os.name"));
        System.out.println("Welcome to the Chicken Fried File System");
        try {
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
            String fromUser = new String();
            String[] readTokens = null;
            long beforeCommand = 0;
            long afterCommand = 0;
            long totalTimeForCommand = 0;
            while (!fromUser.equalsIgnoreCase("EXIT")) {
                System.out.print("CFF$");
                fromUser = stdIn.readLine();
                if (fromUser.trim().toUpperCase().startsWith("!")) {
                    if (fromUser.trim().toUpperCase().startsWith("!PUT")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 2) {
                            if (readTokens[0].equalsIgnoreCase("put") && readTokens[1].length() > 0) {
                                this.localAddFile(new File(readTokens[1]));
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("!LS")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 1) {
                            ArrayList<String> fileNames = this.localGetFileNameList();
                            if (fileNames != null) {
                                System.out.println("Files found: " + fileNames.size());
                                for (int j = 0; j < fileNames.size(); j = j + 1) {
                                    System.out.println("File " + j + 1 + ": " + fileNames.get(j));
                                }
                            }
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            System.out.println("readTokens.length != 1");
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("!GET")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 2) {
                            if (readTokens[0].equalsIgnoreCase("get") && readTokens[1].length() > 0) {
                                this.localGetFile(readTokens[1]);
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("!RM")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 2) {
                            if (readTokens[0].equalsIgnoreCase("get") && readTokens[1].length() > 0) {
                                this.localRemoveFile(readTokens[1]);
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("!DF")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        System.out.println("readTokens Contents:");
                        if (readTokens.length == 1) {
                            long localDiskSpace = this.localGetAvailableDiskSpace();
                            System.out.println("Local disk space: " + localDiskSpace);
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("!FORMAT")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 1) {
                            this.localFormat();
                            System.out.println("Local format");
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }
                } else {
                    if (fromUser.trim().toUpperCase().startsWith("PUT")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 2) {
                            if (readTokens[0].equalsIgnoreCase("put") && readTokens[1].length() > 0) {
                                boolean success = this.addFile(new File(readTokens[1]));
                                if (success) {
                                    System.out.println("File successfully stored with the other chickens.");
                                } else {
                                    System.out.println("File some how flew the coop.");
                                }
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("LS")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 1) {
                            ArrayList<String> fileNames = this.getFileNameList();
                            if (fileNames != null) {
                                System.out.println("Files found: " + fileNames.size());
                                for (int j = 0; j < fileNames.size(); j = j + 1) {
                                    System.out.println("File " + (j + 1) + ": " + fileNames.get(j));
                                }

                            }
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("GET")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 3) {
                            if (readTokens[0].equalsIgnoreCase("get") && readTokens[1].length() > 0) {
                                boolean success = this.getFile(readTokens[1], readTokens[2]);
                                if (success) {
                                    System.out.println("File successfully saved.");
                                } else {
                                    System.out.println("Sorry we burned your chicken.");
                                }
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("RM")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 2) {
                            if (readTokens[0].equalsIgnoreCase("rm") && readTokens[1].length() > 0) {
                                this.removeFile(readTokens[1]);
                                afterCommand = System.currentTimeMillis();
                                totalTimeForCommand = afterCommand - beforeCommand;
                                System.out.println("time: " + totalTimeForCommand + "ms");
                            } else {
                                this.displayFormatMessage(fromUser);
                            }
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("DF")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 1) {
                            this.getAvailableDiskSpace();
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }

                    if (fromUser.trim().toUpperCase().startsWith("FORMAT")) {
                        beforeCommand = System.currentTimeMillis();
                        readTokens = fromUser.split("\\s+");
                        if (readTokens.length == 1) {
                            this.format();
                            System.out.println("Format underway.");
                            afterCommand = System.currentTimeMillis();
                            totalTimeForCommand = afterCommand - beforeCommand;
                            System.out.println("time: " + totalTimeForCommand + "ms");
                        } else {
                            this.displayFormatMessage(fromUser);
                        }
                    }
                }

                if (fromUser.toLowerCase().startsWith("metaip")) {
                    RuntimeSettings.getInstance().setMetaServerIP(fromUser.substring(7));
                }

                if (fromUser.toLowerCase().startsWith("metaport")) {
                    RuntimeSettings.getInstance().setMetaServerPort(Integer.parseInt(fromUser.substring(9)));
                }


                if (!(fromUser.trim().toUpperCase().startsWith("PUT") ||
                        fromUser.trim().toUpperCase().startsWith("GET") ||
                        fromUser.trim().toUpperCase().startsWith("LS") ||
                        fromUser.trim().toUpperCase().startsWith("DF") ||
                        fromUser.trim().toUpperCase().startsWith("RM") ||
                        fromUser.trim().toUpperCase().startsWith("METAIP") ||
                        fromUser.trim().toUpperCase().startsWith("METAPORT") ||
                        fromUser.trim().toUpperCase().startsWith("FORMAT") ||
                        fromUser.trim().toUpperCase().startsWith("!PUT") ||
                        fromUser.trim().toUpperCase().startsWith("!GET") ||
                        fromUser.trim().toUpperCase().startsWith("!LS") ||
                        fromUser.trim().toUpperCase().startsWith("!DF") ||
                        fromUser.trim().toUpperCase().startsWith("!FORMAT") ||
                        fromUser.trim().toUpperCase().startsWith("EXIT"))) {
                    System.out.println("CFFS does not recognize " + fromUser.trim() + ".");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("NuggetShell has been shut down.");
            System.exit(0);
        }
    }
}


